Swift ConcurrencyとNEHotspotConfigurationでシンプルなWi-Fi接続を実装する
Nintendo Switchには撮影したスクリーンショットを「スマートフォンに送る」という機能がある。この機能は、表示されているQRコードをスマートフォンで読み取り、Nintendo Switchが作成したWi-Fiネットワークに接続してスクリーンショットをダウンロードするという手順で動作する。現在開発中のアプリでは、この一連の手作業を自動化することを目指している。
この自動化を実現するために、iOS 11から導入されたNEHotspotConfiguration
とNEHotspotConfigurationManager
を使用する。これらのAPIを使用することで、アプリから動的にWi-Fi接続の制御ができる。
NEHotspotConfiguration
とNEHotspotConfigurationManager
の基本的な使い方については、以下の記事でSINさんが詳しく解説しているので参照してほしい。
本記事では、Swift Concurrencyを活用してより簡潔にWi-Fiホットスポットへの接続を実装する方法を紹介する。
iOSアプリから特定のWi-Fiネットワークに接続する
iOSアプリから特定のWi-Fiネットワークに接続する方法は以下の通り。
1. NEHotspotConfigurationの設定
指定されたSSIDおよびパスフレーズを使ってWi-Fiネットワークに接続する。
この関数では、NEHotspotConfiguration
を作成し、それをNEHotspotConfigurationManager
を通じて適用する。パスワードが提供されている場合は、WPA/WPA2用の設定を作成し、そうでない場合はオープンネットワークの設定を作成する。
Swift ConcurrencyのwithCheckedThrowingContinuation
を使って非同期のエラー処理を行う。これにより、NEHotspotConfigurationManager
のapply
メソッドの完了ハンドラーを非同期に処理できる。
private func connectToWiFi(ssidName: String, passphrase: String?) async throws {
let configuration: NEHotspotConfiguration
if let passphrase = passphrase {
configuration = NEHotspotConfiguration(ssid: ssidName, passphrase: passphrase, isWEP: false)
} else {
configuration = NEHotspotConfiguration(ssid: ssidName)
}
try await withCheckedThrowingContinuation { (continuation: CheckedContinuation<Void, Error>) in
NEHotspotConfigurationManager.shared.apply(configuration) { error in
if let error = error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: ())
}
}
}
}
NEHotspotConfigurationErrorのエラーリスト
Wi-Fiの接続時になんらかの問題が発生するとエラーが投げられる。この関数から投げられるエラー NEHotspotConfigurationError
は下表の通り。エラーに関する詳細な説明はこちらを参照してほしい。
エラー | 説明 |
---|---|
invalid | 無効な設定 |
invalidSSID | 無効なSSID |
invalidWPAPassphrase | 無効なWPAパスフレーズ |
invalidWEPPassphrase | 無効なWEPパスフレーズ |
invalidEAPSettings | 無効なEAP設定 |
invalidHS20Settings | 無効なHS20設定 |
invalidHS20DomainName | 無効なHS20ドメイン名 |
userDenied | ユーザーが許可しなかった |
internal | 内部エラーが発生した |
接続ダイアログでキャンセルをクリックすると userDenied
エラーが投げられる。他のエラーと異なりユーザーが自身で選択して発生させたエラーのため、エラーダイアログを表示させないなどの工夫をすることでユーザーにとって使いやすいアプリになるだろう。
do {
try await connectToWiFi(ssidName: "ssid name", passphrase: "passphrase")
} catch NEHotspotConfigurationError.userDenied {
// ユーザーがキャンセルした場合の処理
print("ユーザーが接続をキャンセルしました")
} catch {
// その他のエラー処理
print("エラーが発生しました: \(error)")
}
2. Wi-Fiへの接続
上記のconnectToWiFi関数を利用して、特定のSSIDに接続するには、以下のようにパラメータを指定して実行する。
try await connectToWiFi(ssidName: "ssid name", passphrase: "passphrase")
3. ホットスポット構成の削除
特定のSSIDの構成を削除するには、以下のようにremoveConfigurationを実行する。
NEHotspotConfigurationManager.shared.removeConfiguration(forSSID: "ssid name")
Wi-Fi接続情報のQRコードフォーマット
Wi-Fiネットワークの設定をQRコードで提供する場合のフォーマットはある程度規格化されているようだ。以下のような形式のQRコードをスキャンすると、デバイスをWi-Fiネットワークに接続できる。詳細はこちらを参照。
例: WIFI:T:WPA;S:mynetwork;P:mypass;H:false;;
フォーマット例:
- WPA/WPA2 Personal:
WIFI:T:WPA;S:MyNetwork;P:mypassword;H:false;;
- WEP:
WIFI:T:WEP;S:MyNetwork;P:mypassword;H:false;;
- オープンネットワーク:
WIFI:T:nopass;S:MyOpenNetwork;H:false;;
各パラメータの説明
パラメータ | 説明 |
---|---|
T | 認証タイプ(例: WPA, WEP, WPA2-EAP, nopass) |
S | SSID(ネットワーク名) |
P | パスワード(認証タイプがnopassの場合は省略可能) |
H | 隠しSSIDかどうか(trueまたはfalse) |
E | EAPメソッド(WPA2-EAPの場合のみ) |
A | 匿名ID(WPA2-EAPの場合のみ) |
I | ID(WPA2-EAPの場合のみ) |
PH2 | フェーズ2メソッド(WPA2-EAPの場合のみ) |
まとめ
NEHotspotConfigurationとNEHotspotConfigurationManagerを使うことで、アプリ内から簡単にWi-Fiネットワークへの接続と切断を管理できる。Swift Concurrencyを利用することで、非同期操作がさらに簡単にできるようになった。